import uaParser from 'ua-parser-js';

import {
    type TokenInfoResponse,
    TOKEN_TYPE_API,
    TOKEN_TYPE_MCP,
    SessionDeviceType,
    SessionInfo
} from '@/models/token.ts';

interface UserAgentInfo {
    readonly device: {
        readonly vendor?: string;
        readonly model?: string;
        readonly type?: string;
    };
    readonly os: {
        readonly name?: string;
        readonly version?: string;
    };
    readonly browser: {
        readonly name?: string;
        readonly version?: string;
    };
}

function parseUserAgent(ua: string): UserAgentInfo {
    const uaParseRet = uaParser(ua);

    return {
        device: {
            vendor: uaParseRet.device.vendor,
            model: uaParseRet.device.model,
            type: uaParseRet.device.type
        },
        os: {
            name: uaParseRet.os.name,
            version: uaParseRet.os.version
        },
        browser: {
            name: uaParseRet.browser.name,
            version: uaParseRet.browser.version
        }
    };
}

function parseDeviceInfo(uaInfo: UserAgentInfo): string {
    if (!uaInfo) {
        return '';
    }

    let result = '';

    if (uaInfo.device && uaInfo.device.model) {
        result = uaInfo.device.model;
    } else if (uaInfo.os && uaInfo.os.name) {
        result = uaInfo.os.name;

        if (uaInfo.os.version) {
            result += ' ' + uaInfo.os.version;
        }
    }

    if (uaInfo.browser && uaInfo.browser.name) {
        let browserInfo = uaInfo.browser.name;

        if (uaInfo.browser.version) {
            browserInfo += ' ' + uaInfo.browser.version;
        }

        if (result) {
            result += ' (' + browserInfo + ')';
        } else {
            result = browserInfo;
        }
    }

    if (!result) {
        return 'Unknown Device';
    }

    return result;
}

export function parseSessionInfo(token: TokenInfoResponse): SessionInfo {
    const isCreateForAPI = token.tokenType === TOKEN_TYPE_API;
    const isCreateForMCP = token.tokenType === TOKEN_TYPE_MCP;
    const uaInfo = parseUserAgent(token.userAgent);
    let deviceType: SessionDeviceType = SessionDeviceType.Default;
    let deviceName: string = 'Other Device';

    if (isCreateForAPI) {
        deviceType = SessionDeviceType.Api;
        deviceName = 'API Token';
    } else if (isCreateForMCP) {
        deviceType = SessionDeviceType.MCP;
        deviceName = 'MCP Token';
    } else {
        if (uaInfo && uaInfo.device) {
            if (uaInfo.device.type === 'mobile') {
                deviceType = SessionDeviceType.Phone;
            } else if (uaInfo.device.type === 'wearable') {
                deviceType = SessionDeviceType.Wearable;
            } else if (uaInfo.device.type === 'tablet') {
                deviceType = SessionDeviceType.Tablet;
            } else if (uaInfo.device.type === 'smarttv') {
                deviceType = SessionDeviceType.TV;
            } else {
                deviceType = SessionDeviceType.Default;
            }
        } else {
            deviceType = SessionDeviceType.Default;
        }

        if (token.isCurrent) {
            deviceName = 'Current';
        } else {
            deviceName = 'Other Device';
        }
    }

    return SessionInfo.of(
        token.tokenId,
        token.isCurrent,
        deviceType,
        isCreateForAPI || isCreateForMCP ? token.userAgent : parseDeviceInfo(uaInfo),
        deviceName,
        token.lastSeen
    );
}
